package shardid

import (
	"testing"

	"github.com/stretchr/testify/require"
)

func TestHR(t *testing.T) {

	// Hash      i
	// 46916880 E0 0
	// 63694499 E1 1
	// 80472118 E2 2
	// 84017712 S2 2
	// 97249737 E3 3
	// 100795331 S3 3
	// 114027356 E4 4
	// 117572950 S0 0
	// 134350569 S1 1
	// 181432022 G4 4
	// 184683426 S4 4
	// 214987260 G2 2
	// 231764879 G3 3
	// 248542498 G0 0
	// 265320117 G1 1
	// 316638712 M0 0
	// 333416331 M1 1
	// 350193950 M2 2
	// 351179688 K2 2
	// 366971569 M3 3
	// 367957307 K3 3
	// 383749188 M4 4
	// 384734926 K0 0
	// 401512545 K1 1
	// 451153854 O4 4
	// 451845402 K4 4
	// 484709092 O2 2
	// 501486711 O3 3
	// 518264330 O0 0
	// 535041949 O1 1
	// 2228889920 C2 2
	// 2245667539 C3 3
	// 2262445158 C0 0
	// 2263430896 I4 4
	// 2279222777 C1 1
	// 2329555634 C4 4
	// 2330541372 I0 0
	// 2347318991 I1 1
	// 2364096610 I2 2
	// 2380874229 I3 3
	// 2530592872 A4 4
	// 2533152728 Q4 4
	// 2597703348 A0 0
	// 2600263204 Q0 0
	// 2614480967 A1 1
	// 2617040823 Q1 1
	// 2631258586 A2 2
	// 2633818442 Q2 2
	// 2648036205 A3 3
	// 2650596061 Q3 3

	// 4294967295 MaxUint32

	tests := []struct {
		name        string
		dbs         int
		data        []string
		wantedDbs   []int
		wantedNodes []uint32
	}{
		// 2439456  1149 <-
		// 46916880 E0 0 <-
		// 117572950 S0 0
		// 248542498 G0 0
		// 316638712 M0 0
		// 384734926 K0 0
		// 518264330 O0 0
		// 2262445158 C0 0
		// 2329555634 C4 <-
		// 2330541372 I0 0
		// 2597703348 A0 0
		// 2600263204 Q0 0 <-
		// 4113327457 150 <-
		{
			name: "single_db_should_work",
			dbs:  1,
			data: []string{
				"1149", // 2439456 < E0
				"E0",   // == E0
				"C4",   // E0 < 2329555634 < Q0
				"Q0",   // == Q0
				"150",  // 2631258586  > Q0
			},
			wantedDbs: []int{
				0,
				0,
				0,
				0,
				0,
			},
			wantedNodes: []uint32{
				46916880,   // E0
				117572950,  // S0
				2330541372, // I0
				46916880,   // E0
				46916880,   // E0
			},
		},
		// 2439456  1149 <-
		// 46916880 E0 0 <-
		// 63694499 E1 1
		// 80472118 E2 2
		// 84017712 S2 2
		// 117572950 S0 0
		// 134350569 S1 1
		// 214987260 G2 2
		// 248542498 G0 0
		// 265320117 G1 1
		// 316638712 M0 0
		// 333416331 M1 1
		// 350193950 M2 2
		// 351179688 K2 2
		// 384734926 K0 0
		// 401512545 K1 1
		// 484709092 O2 2
		// 518264330 O0 0
		// 535041949 O1 1
		// 2228889920 C2 2
		// 2262445158 C0 0
		// 2279222777 C1 1
		// 2329555634 C4 <-
		// 2330541372 I0 0
		// 2347318991 I1 1
		// 2364096610 I2 2
		// 2597703348 A0 0
		// 2600263204 Q0 0
		// 2614480967 A1 1
		// 2617040823 Q1 1
		// 2631258586 A2 2
		// 2633818442 Q2 2 <-
		// 4113327457 150 <-

		{
			name: "multi_dbs_should_work",
			dbs:  3,
			data: []string{
				"1149", // 2439456 < E0
				"E0",   // == E0
				"C4",   // E0 < 2329555634 < Q2
				"Q2",   // == Q2
				"150",  // 2631258586  > Q0
			},
			wantedDbs: []int{
				0,
				1,
				0,
				0,
				0,
			},
			wantedNodes: []uint32{
				46916880,   // E0
				63694499,   // E1
				2330541372, // I0
				46916880,   // E0
				46916880,   // E0
			},
		},
	}

	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			as := require.New(t)
			hr := NewHR(test.dbs)

			for i, v := range test.data {
				d, vn := hr.On(v)
				as.Equal(test.wantedDbs[i], d, v)
				as.Equal(test.wantedNodes[i], vn, v)
			}
		})
	}

}
